;*********************************************************** ; DDSコントロール・プログラム2 ; ;【 動作内容 】 ;  PICリセット後、確認のため PORTB の LED が1秒間点灯する。 ;  パソコンからチップセレクト・コマンドデータ、及び ;  周波数データを、RS232C シリアル通信で送る。 ;  周波数データは、Lower Byte、Middle Byte、Higher Byte ;  の順に、それぞれ 3分割した値を送る。 ;  各データはバッファに一時格納し、データの受信が完了したら、 ;  随時、DDS 設定信号を出力する。 ; ;【 DDS 接続ポート 】 ; (DDS) (PIC) ; STB ………RE0 ; DATA………RE1 ; SCK ………RE2 ; ;【 RS-232C 接続ポート 】 ; 非同期式通信モード ; ボーレート 9600bps ; 8ビット・ノンパリティ ; 割り込みは使用しない ; ;*********************************************************** LIST P=PIC16F877 ; プロセッサの種別指定 INCLUDE "P16F877.INC" ; インクルードファイルの指定 ;*********************************************************** ; 変数定義とレジスタ割付 ;*********************************************************** COUNT EQU 20H ; ループカウンタ COUNT1 EQU 21H ; ループカウンタ1 COUNT2 EQU 22H ; ループカウンタ2 COUNT3 EQU 23H ; ループカウンタ3 COUNT4 EQU 24H ; ループカウンタ4 TEMP EQU 25H ; 一時保管データ COUNT_D EQU 26H ; データカウンタ COUNT_S EQU 27H ; シフトカウンタ ;*********************************************************** ; 初期化 ; (注)バンクの位置に注意 ;*********************************************************** ORG 0 ; プログラムの開始番地の指定 BSF STATUS,RP0 ; Bank 1 へ切替 MOVLW B'00000010' ; RE0,RE1,RE2 デジタル入出力 MOVWF ADCON1 ; ADCON1レジスタの設定 CLRF TRISE ; PORTE 全ポートを出力に設定 CLRF TRISB ; PORTB 全ポートを出力に設定 MOVLW B'10111111' ; RC7/RX(入力),RC6/TX(出力) MOVWF TRISC ; PORTC の設定 MOVLW B'00100100' ; 8BIT,送信許可,非同期,高速 MOVWF TXSTA ; TXSTA レジスタの設定 MOVLW 81H ; ボーレート 9600bps (20MHz:高速設定時) MOVWF SPBRG ; SPBRG レジスタの設定 BCF STATUS,RP0 ; Bank 0 へ戻す MOVLW B'10010000' ; シリアル,8BIT,継続受信許可 MOVWF RCSTA ; RCSTA レジスタの設定 ;*********************************************************** ; メインプログラム ;*********************************************************** ; DDS信号ラインのレベルの初期設定 MOVLW B'00000111' ; SCK,DATA,STB = [H],[H],[H] に設定 MOVWF PORTE ; PORTEへ出力(DDSとの通信の初期設定) MAIN BSF STATUS,IRP ; 間接アドレス設定 MOVLW 0A0H ; バッファの先頭アドレスをセットする MOVWF FSR ; 間接アドレスポインタの初期化 MOVLW 4H ; 4回繰り返す(DDS設定データ) MOVWF COUNT_D ; データカウンタのセット ; データ受信待ちになっていることを確認するためのLED表示 MOVLW B'11111111' ; 11111111 を Wreg にロードする MOVWF PORTB ; PORTBへWregのデータを出力(LEDの点灯) CALL TIME1S ; 1秒のウエイトを入れる MOVLW B'00000000' ; 00000000 を Wreg にロードする MOVWF PORTB ; PORTBへWregのデータを出力(LEDの消灯) LPRCV BTFSS PIR1,RCIF ; USART 受信割り込みフラグビットのチェック GOTO LPRCV ; PIR1 レジスタの RCIF が「0」だったら ; LPRCV ラベル間をループする ; ****** エラーチェック ****** BTFSC RCSTA,FERR ; フレーミングエラーのチェック(1:エラー,0:正常) GOTO FRAME ; フレーミングエラー時 FRAME のラベルへ ; ジャンプする BTFSC RCSTA,OERR ; オーバーランエラーのチェック(1:エラー,0:正常) GOTO OVER ; オーバーランエラー時 OVER のラベルへジャンプする ; ****** 受信データの格納 ****** MOVF RCREG,W ; RCREGレジスタから受信データを読み込む MOVWF INDF ; バッファに格納 INCF FSR,F ; ポインタ +1 DECFSZ COUNT_D,F ; データカウンタ −1 GOTO LPRCV ; LPRCV のラベルへ戻り繰り返す MOVLW 0 ; 25,24ビット目のDDS周波数データ(常に0) MOVWF INDF ; バッファに格納 DDS ; ****** 格納データの取りだし ****** MOVLW 0A0H ; バッファの先頭アドレスをセットする MOVWF FSR ; 間接アドレスポインタをリセットする MOVLW 5H ; 5回繰り返す(DDS設定データ) MOVWF COUNT_D ; データカウンタのセット DDS_SET MOVF INDF,W ; バッファに格納されているデータをWregにロードする MOVWF TEMP ; 一時保管データへ MOVF COUNT_D,W ; データカウンタの値をWregへロードする(OFFSET) CALL TABLE ; シフトカウンタ値の読み込みサブルーチンへ MOVWF COUNT_S ; シフトカウンタのセット DDS_LP RRF TEMP,F ; DDS設定データを取り出す。 BTFSS STATUS,C ; データが1だったら次の命令をスキップ GOTO DATA_L ; DATA = [L] GOTO DATA_H ; DATA = [H] SET_SCK BCF PORTE,2 ; SCK = [L] NOP ; ポートの誤動作防止 BSF PORTE,2 ; SCK = [H] DECFSZ COUNT_S,F ; シフトカウンタ −1 GOTO DDS_LP ; DDS_LP のラベルへ戻り繰り返す INCF FSR,F ; 間接アドレスポインタ +1 DECFSZ COUNT_D,F ; データカウンタ −1 GOTO DDS_SET ; DDS_SET のラベルへ戻り繰り返す BSF PORTE,1 ; DATA = [H] NOP ; ポートの誤動作防止 BCF PORTE,0 ; STB = [L] NOP ; ポートの誤動作防止 BSF PORTE,0 ; STB = [H] GOTO MAIN ; 繰り返しデータ受信動作に入る DATA_L BCF PORTE,1 ; DATA = [L] GOTO SET_SCK DATA_H BSF PORTE,1 ; DATA = [H] GOTO SET_SCK ;*********************************************************** ; シフトカウンタ・テーブル ;*********************************************************** TABLE ; TABLEの定義(PC+OFFSET相当のシフトカウンタ値を持って戻る) ADDWF PCL,F ; PC+OFFSET NOP ; ダミーデータ DT 2,8,8,8,7 ; 各データに対するシフトカウンタ値 ;*********************************************************** ; RS232Cシリアル通信エラー時の処理 ;*********************************************************** FRAME ; <フレーミングエラー時の処理> MOVLW B'00001111' ; 00001111 を Wreg にロードする MOVWF PORTB ; PORTBへWregのデータを出力(LEDの点灯状態でエラーを知らせる) CALL TIME1S ; 1秒のウエイトを入れる MOVLW B'00000000' ; 00000000 を Wreg にロードする MOVWF PORTB ; PORTBへWregのデータを出力(LEDの消灯) MOVF RCREG,W ; ダミーの入力とFERRフラグをリセット(RCREGをリードするとクリア) BTFSS RCSTA,OERR ; オーバーランエラーのチェック(1:エラー,0:正常) GOTO MAIN ; オーバーランエラーがなければ MAIN のラベルへジャンプする ; OVER ; <オーバーランエラー時の処理> MOVLW B'11110000' ; 11110000 を Wreg にロードする MOVWF PORTB ; PORTBへWregのデータを出力(LEDの点灯状態でエラーを知らせる) CALL TIME1S ; 1秒のウエイトを入れる MOVLW B'00000000' ; 00000000 を Wreg にロードする MOVWF PORTB ; PORTBへWregのデータを出力(LEDの消灯) BCF RCSTA,CREN ; OERRのリセット(ビットCREN のクリアによりクリアする) BSF RCSTA,CREN ; 連続受信を許可する GOTO MAIN ; MAIN のラベルへジャンプする ;*********************************************************** ;遅延サブルーチン ;*********************************************************** ;100μs遅延サブルーチン(20MHzクロック時) TIME100 MOVLW 0A5H ; 1サイクル A5H=165 MOVWF COUNT ; 1サイクル NOP ; 1サイクル 微調整ダミー NOP ; 1サイクル 微調整ダミー LOOP DECFSZ COUNT,F ; 1×(165-1)+2 = 166サイクル GOTO LOOP ; 2×(165-1) = 328サイクル RETURN ; 2サイクル ;10ms遅延サブルーチン(20MHzクロック時) TIME10M MOVLW 63H ; 1サイクル 63H=99 MOVWF COUNT1 ; 1サイクル NOP ; 1サイクル 微調整ダミー NOP ; 1サイクル 微調整ダミー LOOP1 CALL TIME100 ; (2+500)×99=49698サイクル DECFSZ COUNT1,F ; 1×(99-1)+2 = 100サイクル GOTO LOOP1 ; 2×(99-1) = 196サイクル RETURN ; 2サイクル ;1s遅延サブルーチン(20MHzクロック時) TIME1S MOVLW 63H ; 1サイクル 63H=99 MOVWF COUNT2 ; 1サイクル MOVLW 62H ; 1サイクル 62H=98 MOVWF COUNT3 ; 1サイクル MOVLW 03H ; 1サイクル 03H=3 MOVWF COUNT4 ; 1サイクル NOP ; 1サイクル 微調整ダミー LOOP2 CALL TIME10M ;(2+50000)×99=4950198サイクル DECFSZ COUNT2,F ; 1×(99-1)+2 = 100サイクル GOTO LOOP2 ; 2×(99-1) = 196サイクル LOOP3 CALL TIME100 ;(2+500)×98=49196 DECFSZ COUNT3,F ; 1×(98-1)+2 = 99サイクル GOTO LOOP3 ; 2×(98-1) = 194サイクル LOOP4 DECFSZ COUNT4,F ; 1×(3-1)+2 = 4サイクル GOTO LOOP4 ; 2×(3-1) = 4サイクル RETURN ; 2サイクル END